"""
PersonalRank算法是一种基于随机游走的推荐算法，用于计算用户对物品的个性化偏好

首先定义了一个名为personal_rank()的函数，用于执行PersonalRank算法。

然后，我们创建了一个示例的用户-物品二分图graph，其中包含了一些用户和物品之间的关联关系。

接下来，我们设置了PersonalRank算法的参数alpha、root、max_iter和tol。

最后，我们调用personal_rank()函数执行PersonalRank算法，得到节点的个性化得分


请注意，PersonalRank算法需要根据具体的问题和数据进行调参。
此外，还可以根据需要对算法进行扩展，如引入随机游走的深度限制、调整随机游走概率的衰减等来改进算法性能。
以上示例代码仅用于理解PersonalRank算法的基本思想和实现方式。



"""


def personal_rank(graph, alpha, root, max_iter=100, tol=1e-6):
    """
    PersonalRank算法实现

    参数:
    - graph: 用户-物品二分图，使用字典表示，键为用户或物品，值为与之关联的用户或物品列表
    - alpha: 随机游走的概率（0 < alpha < 1）
    - root: 随机游走的起始节点
    - max_iter: 最大迭代次数
    - tol: 迭代收敛的阈值

    返回:
    - rank: 节点的个性化得分，使用字典表示，键为节点，值为节点的个性化得分
    """
    rank = {}
    rank_new = {}
    rank[root] = 1.0

    for _ in range(max_iter):
        rank_new = {nodeItem: 0 for nodeItem in rank}
        for item, weight in rank.items():
            neighbors = graph[item]
            for neighbor in neighbors:
                rank_new[neighbor] = rank_new.get(neighbor, 0) + alpha * weight / len(neighbors)
        diff = sum(abs(rank_new[node] - rank[node]) for node in rank)
        if diff < tol:
            break
        rank = rank_new

    return rank


if __name__ == '__main__':
    # 创建一个示例用户-物品二分图
    graph = {
        'user1': ['item1', 'item2', 'item3'],
        'user2': ['item2', 'item3'],
        'user3': ['item1'],
        'item1': ['user1', 'user3'],
        'item2': ['user1', 'user2'],
        'item3': ['user1', 'user2']
    }

    # 设置参数
    alpha = 0.85
    root = 'user1'
    max_iter = 100
    tol = 1e-6

    # 执行PersonalRank算法
    result = personal_rank(graph, alpha, root, max_iter, tol)

    # 输出节点的个性化得分
    print("节点的个性化得分:")
    for node, score in result.items():
        print(f"{node}: {score}")
